<template>
  <el-dialog :title="title" :visible.sync="open" width="600px" append-to-body @close="cancel">
    <el-form ref="form" :model="form" :rules="rules" label-width="80px" :disabled="action == 'view'">
      <template v-for="(f, i) in fieldMode">
        <el-form-item :label="f.label" :prop="f.code" :key="i">
          <!-- 字典  -->
          <el-radio-group v-if="f.type == 'radio'" v-model="form[f.code]">
            <el-radio
              v-for="dict in dataOptions[f.code]"
              :key="dict.value"
              :label="dict.value"
              >{{ dict.label }}</el-radio
            >
          </el-radio-group>
          <el-checkbox-group v-if="f.type == 'checkbox'" v-model="form[f.code]">
            <el-checkbox
              v-for="dict in dataOptions[f.code]"
              :key="dict.value"
              :label="dict.value"
              >{{ dict.label }}</el-checkbox
            >
          </el-checkbox-group>
          <!-- 字典  -->

          <!-- 数据选择  -->
          <el-select 
            v-if="f.type == 'select'"
            v-model="form[f.code]"
            placeholder="请选择"
            clearable filterable
          >
            <el-option
              v-for="dict in dataOptions[f.code]"
              :key="dict.value"
              :label="dict.label"
              :value="dict.value"
            />
          </el-select>
          <treeselect
            v-if="f.type == 'tree'"
            v-model="form[f.code]"
            :options="dataOptions[f.code]"
            :normalizer="normalizer"
            placeholder="请选择"
          />
          <!-- 数据选择  -->

          <!-- 日期/时间 -->
          <el-date-picker
            clearable :readonly="f.readonly"
            v-if="f.type == 'date'"
            v-model="form[f.code]"
            type="date"
            value-format="yyyy-MM-dd"
            placeholder="请选择"
          >
          </el-date-picker>
          <el-date-picker
            clearable :readonly="f.readonly"
            v-if="f.type == 'datetime'"
            v-model="form[f.code]"
            type="datetime"
            value-format="yyyy-MM-dd HH:mm:ss"
            placeholder="请选择"
          >
          </el-date-picker>
          <!-- 日期/时间 -->

          <!-- 上传/预览 -->
          <image-upload v-model="form[f.code]" v-if="f.type == 'images' && !f.readonly" />
          <image-preview :src="form[f.code]" v-if="f.type == 'images' && f.readonly" />
          <!-- 上传/预览 -->


          <!-- 扫码，带数据源，新增时，扫码之后自动取数据，id字段作为字段值 -->
          <el-input focus @keyup.enter.native="getScan(f.code)"
            v-if="f.type == 'scan' && action == 'add' && f.ds"
            v-model="form[f.code+'_code']"
            :placeholder="'请扫码或者输入' + f.label" @change="getScan(f.code)" 
            clearable
          ><template slot="append">{{form[f.code+'_name']}}</template>
          </el-input>
          <el-input v-if="f.type == 'scan' && f.ds" type="hidden" :v-show="false" style="display:none" v-model="form[f.code]"/>          
          <!-- 扫码，带数据源新增 -->
          
          <!-- 扫码，无数据源，新增时扫码结果即字段值 -->
          <el-input focus 
            v-if="f.type == 'scan' && action == 'add' && !f.ds"
            v-model="form[f.code]"
            :placeholder="'请扫码或者输入' + f.label" 
            clearable
          />
          <!-- 扫码，无数据源新增 -->
          
          <!-- 扫码，非新增时只读code和name字段 -->
          <el-input readonly
            v-if="f.type == 'scan' && action !='add'"
            v-model="form[f.code+'_code']"
            :placeholder="'请输入' + f.label"
          ><template slot="append">{{form[f.code+'_name']}}</template>
          </el-input>
          <!-- 扫码，非新增时只读 -->

          <!-- 普通输入 -->
          <el-input-number v-if="f.type == 'number'" :readonly="f.readonly" clearable
              v-model="form[f.code]"  :placeholder="'请输入' + f.label"      />
          <el-input   v-if="f.type == 'text'" :readonly="f.readonly" clearable
              v-model="form[f.code]"            :placeholder="'请输入' + f.label" />          
          <el-input type="textarea" rows="3" :readonly="f.readonly" clearable
              v-if="f.type == 'textarea'" v-model="form[f.code]"  :placeholder="'请输入' + f.label" />
        </el-form-item>
          <!-- 普通输入 -->
      </template>
    </el-form>
    <div slot="footer" class="dialog-footer">
      <el-button type="primary" @click="submitForm">确 定</el-button>
      <el-button @click="cancel">取 消</el-button>
    </div>
  </el-dialog>
</template>

<script>
import { restGet, apiDs } from "@/api/openapi";
import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css";

export default {
  name: "FormDialog",
  components: {    Treeselect  },
  dicts: [],
  props: {
    //标题
    title: String,
    //是否显示
    action: String,
    //数据模型
    fields: Array,
    data: Object
  },
  data() {
    return {
      open: false,
      dataOptions: {},
      fieldMode: {},
      fieldForm: {},
      form: {},
      // 表单校验
      rules: {
      }
    };
  },
  computed: {
    opened: function(){
      return this.action != null;
    }
  },
  created() {
    this.initField();
  },
  watch: {
    data: function(val) {
      this.parseData();
    },
    action: function(val) {
      this.open = (this.action != null)
    }
  },
  methods: {
    initField() {
      let params = {};
      let ps = [];
      let that = this;
      for (var i = 0; i < this.fields.length; i++) {
        params[this.fields[i].code] = null;
        if (this.fields[i].form == '4') {
          continue;
        }
        let field = this.fields[i];
        if (field.type == "radio") {
          ps.push(new Promise((resolve, reject) =>{
            apiDs('sys_dict_select',{dict:field.ds}).then((res) => {
              that.dataOptions[field.code] = res.data;
              resolve();
            });
          }));          
        } else if (field.type == "checkbox") {
          params[field.code] = [];
          ps.push(new Promise((resolve, reject) =>{
            apiDs('sys_dict_select',{dict:field.ds}).then((res) => {
              that.dataOptions[field.code] = res.data;
              resolve();
            });
          }));          
        } else if (field.type == "select") {
          this.dataOptions[field.code] = [];
          ps.push(new Promise((resolve, reject) =>{
            apiDs(field.ds).then((res) => {
              that.dataOptions[field.code] = res.data;
              resolve();
            });
          }));
        } else if (field.type == "tree") {
          this.dataOptions[field.code] = [];
          ps.push(new Promise((resolve, reject) =>{
            apiDs(field.ds).then((res) => {
              const treeOptions = { value: 0, label: '顶级节点', children: [] };
              treeOptions.children = this.handleTree(res.data, "value", "pid");
              that.dataOptions[field.code] = [treeOptions];
              resolve();
            });
          }));
        }

        let rule = [];
        if (field.required == "Y") {
          rule.push({
            required: true,
            message: field.label + "不能为空",
            trigger: "blur",
          });
        }
        if (field.rules) {
          rule.push({
            type: field.rules,
            message: field.label + "不符合规则",
            trigger: "blur",
          });
        }
        if (rule.length > 0) {
          this.rules[field.code] = rule;
        }
      }
      
      if(ps.length > 0){
        Promise.all(ps).then(res=>{
          this.$forceUpdate();
        })
      }
      this.fieldForm = params;
      this.parseData();
    },
    parseData(){
      if(this.data == null){
        this.form = this.fieldForm;
        return;
      }
      let that = this;
      let form = {...this.fieldForm};
      let fieldMode = [];
      this.fields.forEach(f=>{
        if(f.type == 'date' && this.data[f.code]){
          form[f.code] = this.parseTime(this.data[f.code], '{y}-{m}-{d}');
        }else if(f.type == 'datetime' && this.data[f.code]){
          form[f.code] = this.parseTime(this.data[f.code], '{y}-{m}-{d} {h}:{i}:{s}');
        }else if(f.type == 'checkbox' && this.data[f.code]){
          form[f.code] = this.data[f.code].split(',');
        }else if(f.type == 'scan' && this.data[f.code]){
          apiDs(f.ds, {id: this.data[f.code]}).then(res => {
            if(res.data && res.data.length>0){
              that.$set(that.form, f.code+"_code", res.data[0]['code'])
              that.$set(that.form, f.code+"_name", res.data[0]['name'])
            }				
          });
          form[f.code] = this.data[f.code];
          form[f.field+"_code"] = null;
          form[f.field+"_name"] = null;
        }else if(f.defaults != '' && this.data[f.code] == undefined){
          form[f.code] = f.defaults;
        }else{
          form[f.code] = this.data[f.code];
        }

        //动态生成表单字段
        let field = {...f};
        if(this.action == 'view'){
          field.readonly = true;
        }else{
          field.readonly = false;
        }
        
        if(f.mode == '4'){
          //隐藏
          ;
        }else if(f.mode == '3' && this.action != 'view'){
          //只读
          ;
        }else if(f.mode == '1' && this.action == 'edit'){
          //新增
          ;
        }else if(f.mode == '2' && this.action == 'add'){
          //编辑
          ;
        }else{
          fieldMode.push(field);
        }
      })
      console.log(form);
      this.fieldMode = fieldMode;
      this.form = form;
    },
    /** 转换树结构 */
    normalizer(node) {
      if (node.children && !node.children.length) {
        delete node.children;
      }
      return {
        id: node.value,
        label: node.label,
        children: node.children,
      };
    },
    getScan(field) {
				if(!this.form[field+"_code"]){
					this.form[field] = null;
					return;
				}
				
				let f = null;
				for(var i=0;i<this.fields.length;i++){
					f = this.fields[i];
					if(f.code == field){
						break;
					}
				}
				
				if(!f.ds){
          this.form[field] = this.form[field+"_code"];
          console.error('no ds');
					return;
				}
				
				apiDs(f.ds, {code: this.form[field+"_code"]}).then(response => {
					if(response.data && response.data.length>0){
						this.form[field] = response.data[0]['id'];	
						this.form[field+"_name"] = response.data[0]['name'];
						this.form[field+"_code"] = response.data[0]['code'];
					}else{
						this.$modal.msgError("无效的 "+f.label+' 条码');
						this.form[field+"_code"] = null;
						this.form[field+"_name"] = null;
						this.form[field] = null;
					}					
				});
			},
    /** 取消按钮操作 */
    cancel() {
      this.form = this.fieldForm;
      this.$emit("cancel");
    },
    // 提交处理
    submitForm() {
      this.$refs["form"].validate((valid) => {
        if (valid) {
          this.$emit("submit", this.form);
        }
      });
    },
  },
};
</script>
<!--
表单的数据来自列表（编辑或查询），目前不再次调用接口，表单字段业务逻辑如下：
1、普通输入文本/数字/文字（长文本）
2、日期/日期时间调用标准控件
3、图片上传/文件上传，其中图片支持预览
4、字典内容支持多选和单选
5、其它业务数据单选和树形下拉，需要指定数据源，不支持多选

扫码枪
1、扫描未知条码，对应实体数据第一次进入本系统，只需要知道代码值即可；
1.1 如扫描一个设备编码，然后完善信息后保存入库，成为内置数据
1.2 或者搜索框里扫到编码进行搜索
2、扫描已有条码，对应实体数据已经在本系统中，在业务操作时，需要通过扫描编码，快速定位到对应数据
2.1 首先需要在字段（如asset_id）上配置数据源，支持code和id两个参数（二选一）
2.2 在新增操作时，扫码完成后以code做为参数查询时，要至少返回id（主键）和name（重点信息）两个数据，扫码结果会给asset_id_code,通过数据源查询到的id值赋给asset_id,name赋值给asset_id_name；
2.3 回显时以id做为参数进行查询时，要至少返回code（条码）和name（重点信息）两个数据，code赋值给asset_id_code，name赋值给asset_id_name；
2.4 asset_id_code和asset_id_name两个字段是自动创建的，如果有冗余的需要，也可以直接保存入库
2.5 这三个字段，只有asset_id_code可以在新增时扫码或者输入，其它时候都不可编辑，只做回显
--!>
